//
//  ViewController.swift
//  UIKitApp
//
//  Created by changlei on 2021/11/4.
//
//

import UIKit


class DetailController: BaseController {
    private var viewable: Viewable!

    lazy private var scrollViewDelegate: UIScrollViewDelegate = {
        ScrollViewDelegate(host: self, cover: cover, container: container)
    }()
    lazy private var scrollView: UIScrollView = {
        let uiScrollView = UIScrollView()
        uiScrollView.contentInsetAdjustmentBehavior = .never
        uiScrollView.automaticallyAdjustsScrollIndicatorInsets = false
        uiScrollView.alwaysBounceVertical = true
        uiScrollView.delegate = scrollViewDelegate
        return uiScrollView
    }()
    lazy private var cover: UIImageView = {
        let uiImageView = UIImageView()
        uiImageView.contentMode = .scaleAspectFill
        uiImageView.clipsToBounds = true
        uiImageView.kf.setImage(with: URL(string: viewable.cover))
        return uiImageView
    }()
    lazy private var container: UIView = {
        let uiView = UIView()
        uiView.backgroundColor = .systemBlue.withAlphaComponent(0.6)
        return uiView
    }()

    convenience init(_ viewable: Viewable) {
        self.init()
        self.viewable = viewable
    }

    override func viewWillAppear(_ animated: Bool) {
        super.viewWillAppear(animated)
        let scrollEdgeAppearance = scrollEdgeAppearance
        scrollEdgeAppearance?.configureWithTransparentBackground()
        scrollEdgeAppearance?.titleTextAttributes = [.foregroundColor: UIColor.clear]
        navigationItem.scrollEdgeAppearance = scrollEdgeAppearance
    }

    override func viewDidLoad() {
        super.viewDidLoad()
        title = viewable.title

        view.addSubview(scrollView)
        scrollView.snp.makeConstraints { make in
            make.edges.equalToSuperview()
        }

        scrollView.addSubview(cover)
        cover.snp.makeConstraints { make in
            make.width.equalToSuperview()
            make.height.equalTo(view.snp.width).multipliedBy(viewable.coverRate).priority(.high)
            make.leading.top.trailing.equalToSuperview()
            make.bottom.lessThanOrEqualToSuperview()
        }

        scrollView.addSubview(container)
        container.snp.makeConstraints { make in
            make.leading.trailing.width.equalToSuperview()
            make.top.equalTo(cover).offset(view.bounds.width * 3 / 4)
            make.height.equalTo(1000)
            make.bottom.equalToSuperview()
        }
    }
}

private class ScrollViewDelegate: NSObject, UIScrollViewDelegate {
    private weak var host: BaseController?

    private let cover: UIView
    private let container: UIView

    private var isTouchOut: Bool = false

    init(host: BaseController, cover: UIView, container: UIView) {
        self.host = host
        self.cover = cover
        self.container = container
        super.init()
        setStandardAppearance(isTouchOut: isTouchOut)
        setBackButton(isTouchOut: isTouchOut)
    }

    public func scrollViewDidScroll(_ scrollView: UIScrollView) {
        if cover.bounds == CGRect.zero {
            return
        }

        let offsetY = scrollView.contentOffset.y
        offsetCover(offsetY)
        offsetNavigationBar(offsetY)
    }

    private func offsetCover(_ offsetY: Double) {
        let coverHeight = cover.bounds.height
        let transform = CGAffineTransform.identity
        if offsetY <= 0 {
            let scale = 1.0 - offsetY / coverHeight
            cover.transform = transform.translatedBy(x: 0, y: offsetY / 2.0).scaledBy(x: scale, y: scale)
        } else {
            cover.transform = transform
        }
    }

    private func offsetNavigationBar(_ offsetY: Double) {
        guard let navigationBar = host?.navigationBar, let view = host?.view else {
            return
        }
        let navigationBarBottom = navigationBar.convert(navigationBar.bounds, to: view).maxY
        let containerTop = container.convert(container.bounds, to: view).minY
        let isTouchOut = containerTop <= navigationBarBottom
        if isTouchOut != self.isTouchOut {
            self.isTouchOut = isTouchOut
            setStandardAppearance(isTouchOut: isTouchOut)
            setBackButton(isTouchOut: isTouchOut)
        }
    }

    private func setStandardAppearance(isTouchOut: Bool) {
        let standardAppearance = host?.standardAppearance
        if isTouchOut {
            standardAppearance?.configureWithDefaultBackground()
            standardAppearance?.titleTextAttributes = [.foregroundColor: UIColor.label]
        } else {
            standardAppearance?.configureWithTransparentBackground()
            standardAppearance?.titleTextAttributes = [.foregroundColor: UIColor.clear]
        }
        host?.navigationItem.standardAppearance = standardAppearance
    }

    private func setBackButton(isTouchOut: Bool) {
        guard let navigationItem = host?.navigationItem else {
            return
        }
        if isTouchOut {
            navigationItem.setLeftBarButton(nil, animated: true)
        } else {
            let buttonItem = UIBarButtonItem(image: UIImage(systemName: "chevron.backward.circle.fill"))
            buttonItem.style = .plain
            buttonItem.target = self
            buttonItem.action = #selector(onBack)
            buttonItem.tintColor = .white
            navigationItem.setLeftBarButton(buttonItem, animated: true)
        }
    }

    @objc private func onBack() {
        host?.navigationController?.popViewController(animated: true)
    }
}